package com.zoe.app.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zoe.app.annotation.Log;
import com.zoe.app.dao.UsersMapper;
import com.zoe.app.entity.Users;
import com.zoe.app.service.RoleService;
import com.zoe.app.service.UsersService;
import lombok.RequiredArgsConstructor;
import org.springframework.aop.framework.AopContext;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.List;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;

/**
 * @author zoe.Zhang
 * @date 2023/01/30
 * @description $description
 */
@Service
@RequiredArgsConstructor
public class UsersServiceImpl extends ServiceImpl<UsersMapper, Users> implements UsersService {

    private final RoleService roleService;

    private final ThreadPoolTaskExecutor threadPoolTaskExecutor;

    private final TransactionTemplate transactionTemplate;

    /**
     * 插入一条记录（选择字段，策略插入）
     * @param entity 实体对象
     */
    @Override
    @Transactional
    @Log(name = "user")
    public boolean save(Users entity) {
        boolean b = baseMapper.insert(entity) > 0;
        // int i = 1 / 0;
        return b;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean threadTransaction(List<Users> users, Integer num) {
        // List<List<Users>> skip = CollUtil.toList();
        // int pageSize = 2;
        // int totalCount = (int) Math.ceil((Convert.toDouble(users.size()) / pageSize));
        // for (int i = 0; i < totalCount; i++) {
        //     List<Users> collect = users.stream()
        //                                .skip((long) i * pageSize)
        //                                .limit(pageSize)
        //                                .collect(Collectors.toList());
        //     int finalI = i;
        //     CompletableFuture.runAsync(() -> {
        //         PlatformTransactionManager transactionManager = Objects.requireNonNull(transactionTemplate.getTransactionManager());
        //         DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
        //         transactionDefinition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_UNCOMMITTED);
        //         TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition);
        //         try {
        //             saveBatch(collect);
        //             Assert.isTrue(finalI != 2, "异常");
        //             transactionManager.commit(transactionStatus);
        //         }
        //         catch (Throwable e) {
        //             transactionManager.rollback(transactionStatus);
        //             // throw e;
        //         }
        //     }, threadPoolTaskExecutor).join();
        // }
        //
        // System.out.println(skip);
        // return true;
        List<List<Users>> listList = CollUtil.split(users, num); // 切片

        for (int i = 0; i < listList.size(); i++) {
            List<Users> collect = listList.get(i);
            int finalI = i;
            // 这里启动了多线程的方式来插入，但是会有一个问题：
            // 0-100 101-200 201-300 301-400这些批次，这里的事务控制不能控制整个全局的批次事务,只能控制某一个批次出现异常后,进行回滚操作;
            CompletableFuture.runAsync(() -> {
                PlatformTransactionManager transactionManager = Objects.requireNonNull(transactionTemplate.getTransactionManager());
                DefaultTransactionDefinition transactionDefinition = new DefaultTransactionDefinition();
                transactionDefinition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_UNCOMMITTED);
                TransactionStatus transactionStatus = transactionManager.getTransaction(transactionDefinition);
                try {
                    saveBatch(collect);
                    Assert.isTrue(finalI != 2, "异常");
                    transactionManager.commit(transactionStatus);
                } catch (Throwable e) {
                    transactionManager.rollback(transactionStatus);
                    // throw e;
                }
            }, threadPoolTaskExecutor).join();
        }
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveUser() {
        Users users = new Users();
        users.setUsername("张三" + IdUtil.fastSimpleUUID());
        users.setPassword(IdUtil.nanoId());
        save(users);
        boolean b = roleService.saveRoleAndMenu();
        // System.out.println(1/0);
        return b;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean thisSave() {
        Users users = new Users();
        users.setUsername("张三" + IdUtil.fastSimpleUUID());
        users.setPassword(IdUtil.nanoId());
        save(users);
        UsersService o = (UsersService) AopContext.currentProxy();
        o.saveRoleAndMenu();
        return false;
    }

    @Log
    public void saveRoleAndMenu() {
        boolean b = roleService.saveRoleAndMenu();
        System.out.println(1 / 0);
    }
}
